package com.mes.cloud.service;

import com.mes.cloud.api.dto.request.employee.ResetPwdRequest;
import com.mes.cloud.api.dto.request.employee.UpdatePwdRequest;
import com.mes.cloud.exception.BaseException;
import com.mes.cloud.common.JsonResult;
import com.mes.cloud.constant.Constants;
import com.mes.cloud.dao.BaseEmployeeDao;
import com.mes.cloud.entity.BaseEmployee;
import com.mes.cloud.entity.LoginParamRequest;
import com.mes.cloud.entity.LoginUser;
import com.mes.cloud.enums.HttpStatusEnum;
import com.mes.cloud.jedis.util.RedisUtil;
import com.mes.cloud.util.MD5Util;
import com.mes.cloud.util.UserUtil;
import com.mes.cloud.utils.AESUtils;
import com.mes.cloud.utils.RSAUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.security.KeyPair;
import java.util.UUID;

/**
 * @author Mr.zhang
 * @description 登录
 * @email zhangchao4@shinho.net.cn
 * @date 2019/11/28 15:02
 **/
@Service("loginService")
public class LoginService {

    private RedisUtil redisUtil;
    private BaseEmployeeDao baseEmployeeDao;

    @Autowired
    public LoginService(RedisUtil redisUtil,
                        BaseEmployeeDao baseEmployeeDao) {
        this.redisUtil = redisUtil;
        this.baseEmployeeDao = baseEmployeeDao;
    }

    /**
     * 系统登录
     *
     * @param loginParams
     * @return
     */
    public JsonResult<LoginUser> login(LoginParamRequest loginParams)  {
        //获取员工信息
        BaseEmployee entity = new BaseEmployee();
        entity.setEmployeeNo(loginParams.getUsername().trim());
        BaseEmployee baseEmployee = baseEmployeeDao.selectOne(entity);
        if (baseEmployee == null) {
            throw new BaseException(HttpStatusEnum.BAD_REQUEST.getCode(), "系统开小差了");
        }
        if (Constants.DEL_FLAG_YES.equals(baseEmployee.getDelFlag())
                || Constants.ENABLE_FLAG_NO.equals(baseEmployee.getEnableFlag())
                || Constants.ALLOW_LOGIN_NO.equals(baseEmployee.getAllowLogin())) {
            throw new BaseException(HttpStatusEnum.BAD_REQUEST.getCode(), "用户名或者密码错误");
        }
        //用私钥解密
        String privateKey = redisUtil.get(Constants.LOGIN_KEY_PAIR, loginParams.getUsername());
        String password = "";
        try {
            password = RSAUtil.decrypt(loginParams.getPassword(), privateKey);
        } catch (Exception e) {
            throw new BaseException(HttpStatusEnum.BAD_REQUEST.getCode(), "用户名或者密码错误");
        } finally {
        }
        //删除当前的秘钥对，确保一个秘钥对只一次登录有效
        redisUtil.delete(Constants.LOGIN_KEY_PAIR, loginParams.getUsername());
        //AES加密
        String pwdencrypAES = AESUtils.encryptData(password, Constants.PWD_KEY, Constants.PWD_KEY);
        //判断密码是否一致
        if (!pwdencrypAES.equals(baseEmployee.getPwd())) {
            throw new BaseException(HttpStatusEnum.BAD_REQUEST.getCode(), "用户名或者密码错误");
        }
        //设置token
        String token = MD5Util.md5(UUID.randomUUID().toString());
        // 获取用户，并存入redis
        redisUtil.set(token, loginParams.getUsername(), Constants.LOGIN_INFO_EXPIRE);
        LoginUser loginUser = new LoginUser();
        loginUser.setAccessToken(token);
        loginUser.setEmployeeNo(loginParams.getUsername());
        return new JsonResult<>(loginUser);
    }

    public JsonResult logout(HttpServletRequest request, String platform) {
        //从header中获取token
        String accessToken = request.getHeader("Authorization");
        if (StringUtils.isEmpty(accessToken)) {
            return new JsonResult().setMsg("退出失败！accessToken值为空").setCode(HttpStatusEnum.BAD_REQUEST.getCode());
        }
        String employeeNo = redisUtil.get(accessToken, String.class);
        redisUtil.delete(accessToken);
        String employeeNoAuth = employeeNo + Constants.AUTH_REDIS_SUFFIX;
        if (redisUtil.hasKey(employeeNoAuth)) {
            redisUtil.delete(employeeNoAuth);
        }
        String employeeNoInfo = employeeNo + Constants.USER_REDIS_SUFFIX;
        if (redisUtil.hasKey(employeeNoInfo)) {
            redisUtil.delete(employeeNoInfo);
        }
        //清理用户菜单权限缓存
        if (redisUtil.hasKey(Constants.MY_MENU_LIST, employeeNo + platform)) {
            redisUtil.delete(Constants.MY_MENU_LIST, employeeNo + platform);
        }
        //清理岗位
        String employeePositionKey = employeeNo + Constants.POSITION_REDIS_SUFFIX;
        if (redisUtil.hasKey(employeePositionKey)) {
            redisUtil.delete(employeePositionKey);
        }
        return JsonResult.ok();
    }


    public JsonResult get(String employeeNo) {
        employeeNo = employeeNo.trim();
        //获取员工信息
        BaseEmployee entity = new BaseEmployee();
        entity.setEmployeeNo(employeeNo);
        int count = baseEmployeeDao.selectCount(entity);
        if (count == 0) {
            throw new BaseException(HttpStatusEnum.BAD_REQUEST.getCode(), "用户名或者密码错误");
        }
        //获取秘钥对
        try {
            KeyPair keyPair = RSAUtil.genKeyPair();
            String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
            String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
            redisUtil.set(Constants.LOGIN_KEY_PAIR, employeeNo, privateKey);
            System.out.println(RSAUtil.encrypt("123456", publicKey));
            return JsonResult.ok().setData(publicKey);
        } catch (Exception e) {
            throw new BaseException(HttpStatusEnum.BAD_REQUEST.getCode(), "获取秘钥对失败");
        }
    }

    //更新密码
    public JsonResult updatePwd(UpdatePwdRequest updatePwdRequest) {
        //获取用户信息
        BaseEmployee entity = new BaseEmployee();
        entity.setEmployeeNo(UserUtil.getEmployeeNo());
        BaseEmployee baseEmployee = baseEmployeeDao.selectOne(entity);
        //用私钥解密
        String privateKey = redisUtil.get(Constants.LOGIN_KEY_PAIR, UserUtil.getEmployeeNo());
        String password = "";
        try {
            password = RSAUtil.decrypt(updatePwdRequest.getOldPwd(), privateKey);
        } catch (Exception e) {
            throw new BaseException(HttpStatusEnum.BAD_REQUEST.getCode(), "用户名或者密码错误");
        } finally {
            //删除当前的秘钥对，确保一个秘钥对只一次登录有效
            redisUtil.delete(Constants.LOGIN_KEY_PAIR, UserUtil.getEmployeeNo());
        }
        //AES加密
        String pwdencrypAES = AESUtils.encryptData(password, Constants.PWD_KEY, Constants.PWD_KEY);
        //判断密码是否一致
        if (!pwdencrypAES.equals(baseEmployee.getPwd())) {
            throw new BaseException(HttpStatusEnum.BAD_REQUEST.getCode(), "原密码错误");
        }

        BaseEmployee baseEmployeeUpdatePwd = new BaseEmployee();
        baseEmployeeUpdatePwd.setId(baseEmployee.getId());
        baseEmployeeUpdatePwd.setPwd(AESUtils.encryptData(updatePwdRequest.getNewPwd(),Constants.PWD_KEY,Constants.PWD_KEY));
        baseEmployeeDao.updateByPrimaryKeySelective(baseEmployeeUpdatePwd);
        return JsonResult.ok();
    }

    //重置密码
    public JsonResult resetPwd(ResetPwdRequest resetPwdRequest) {
        BaseEmployee baseEmployee = new BaseEmployee();
        baseEmployee.setId(resetPwdRequest.getId());
        baseEmployee.setPwd(Constants.PWD_DEFAULT);
        baseEmployeeDao.updateByPrimaryKeySelective(baseEmployee);
        return JsonResult.ok();
    }
}
